package com.situ.object.utils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/*
* 增删改查
* */
public class DBUtil {
    //查询操作
    //<T> T 表示返回值是一个泛型(返回一个任意类型的数据)
    //Class<T> cls表示class类对象，String sql表示sql语句，Object... params传递的参数的（多个）
    public  <T> T queryOne(Class<T> cls, String sql, Object... params) {
        //创建一个返回值为T类型的对象
        T result = null;
        Connection connection = null;
        //创建执行对象 对sql语句进行预处理
        PreparedStatement preparedStatement = null;
        //ResultSet接口：表示数据库结果集的数据表，通常通过执行查询数据库的语句生成。
        //结果集 (ResultSet) 是数据中查询结果返回的一种对象，可以说结果集是一个存储查询结果的对象，
        //但是结果集并不仅仅具有存储的功能，他同时还具有操纵数据的功能，可能完成对数据的更新
        ResultSet resultSet = null;
        try {
            //创建连接
            connection = JdbcUtil.getConnection();
            //sql预处理
            preparedStatement = connection.prepareStatement(sql);
            //遍历数组
            if (params != null && params.length > 0) {
                for (int i = 0; i < params.length; i++) {
                    //给sql的占位符？赋值
                    preparedStatement.setObject(i + 1, params[i]);
                }
            }
            //执行数据查询，将查询结果传给结果集
            resultSet = preparedStatement.executeQuery();

            //获取结果集的元数据
            //元数据：描述数据的数据
            ResultSetMetaData data = resultSet.getMetaData();
            //获取结果集的行数
            //分别是：id,username,password,status
            int count = data.getColumnCount();
            if (resultSet.next()) {
                //创建类
                T t = cls.newInstance();
                for (int i = 1; i <= count; i++) {
                    //分别返回id
                    String colName = data.getColumnName(i);
                    Object value = resultSet.getObject(colName);
                    //内省Java Bean并了解其所有属性、暴露的方法和事件
                    BeanInfo beanInfo = Introspector.getBeanInfo(cls);
                    //返回bean的所有属性的描述符
                    PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
                    for (PropertyDescriptor prop : props) {
                        //获取此功能的编程名称
                        if (prop.getName().equals(colName)) {
                            //同一列 set方法赋值
                            //获取应用与写入属性值的方法
                            Method setter = prop.getWriteMethod();

                            //DATETIME时间处理 开始
                            String type = resultSet.getMetaData().getColumnTypeName(i);
                            if("DATETIME".equals(type)){
                                String datetime = resultSet.getString(i);
                                if(datetime != null) {
                                    try {
                                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                                        setter.invoke(t, LocalDateTime.parse(datetime, formatter));
                                    }catch (Exception e){
                                        setter.invoke(t);
                                    }
                                }
                            }else {
                                setter.invoke(t, value);
                            }
                            //DATETIME时间处理 结束

                            //setter.invoke(t, value);

                        }
                    }
                }
                result = t;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("连接异常");
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {
            JdbcUtil.close(connection, resultSet, preparedStatement);
            return result;
        }
    }


    public  <T> List<T> query(Class<T> cls, String sql, Object... params) {
        List<T> list = new ArrayList<>();
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection = JdbcUtil.getConnection();
            //String sql = "select * from account where username = ?";
            preparedStatement = connection.prepareStatement(sql);
            //遍历数组
            if (params != null && params.length > 0) {
                for (int i = 0; i < params.length; i++) {
                    preparedStatement.setObject(i + 1, params[i]);
                }
            }

            resultSet = preparedStatement.executeQuery();
            //得到结果集数据
            ResultSetMetaData data = resultSet.getMetaData();
            int count = data.getColumnCount();
            while (resultSet.next()) {
                T t = cls.newInstance();
                for (int i = 1;i<=count;i++){
                    String colName = data.getColumnName(i);
                    Object value = resultSet.getObject(colName);
                    //内省Java Bean并了解其所有属性、暴露的方法和事件
                    BeanInfo beanInfo = Introspector.getBeanInfo(cls);
                    //返回bean的所有属性的描述符
                    PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
                    for (PropertyDescriptor prop : props){
                        //获取此功能的编程名称
                        if (prop.getName().equals(colName)){
                            //同一列 set方法赋值
                            //获取应用与写入属性值的方法
                            Method setter = prop.getWriteMethod();

                            //DATETIME时间处理 开始
                            String type = resultSet.getMetaData().getColumnTypeName(i);
                            if("DATETIME".equals(type)){
                                String datetime = resultSet.getString(i);
                                if(datetime != null) {
                                    try {
                                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                                        setter.invoke(t, LocalDateTime.parse(datetime, formatter));
                                    }catch (Exception e){
                                        setter.invoke(t);
                                    }
                                }
                            }else {
                                setter.invoke(t, value);
                            }
                            //DATETIME时间处理 结束

                            //setter.invoke(t,value);
                        }
                    }
//                    String setName = "set" + colName.substring(0,1).toUpperCase() + colName.substring(1);
//                    Method[] methods = cls.getDeclaredMethods();
//                    for (Method method : methods){
//                        if (method.getName().equals(setName)){
//                            method.invoke(t,value);
//                        }
//                    }
                }
//                Integer id = resultSet.getInt("id");
//                String username = resultSet.getString("username");
//                String cardnum = resultSet.getString("cardnum");
//                BigDecimal money = resultSet.getBigDecimal("money");
//                Account account = new Account();
//                account.setId(id);
//                account.setUsername(username);
//                account.setCardnum(cardnum);
//                account.setMoney(money);
                list.add(t);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("连接异常");
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {
            JdbcUtil.close(connection, resultSet, preparedStatement);
            return list;
        }
    }

    //增删改
    public int update(String sql,Object... params){
        int result = 0;
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = JdbcUtil.getConnection();

            //预编译
            preparedStatement = connection.prepareStatement(sql);
            if (params != null && params.length > 0) {
                for (int i = 0; i < params.length; i++) {
                    preparedStatement.setObject(i + 1, params[i]);
                }
            }
            result = preparedStatement.executeUpdate();

        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("连接异常");
        }finally {
            JdbcUtil.close(connection,null, preparedStatement);
            //System.out.println("qwe"+ result);
            return result;
        }
    }
}
